package dao

import (
	"bytes"
	"common/logs"
	"common/rsa"
	"common/utils"
	"context"
	db "core/models/db"
	"core/models/entity"
	"core/repo"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"framework/game"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	hall "hall/pay/entity"
	"hall/pay/service"
	"io"
	"io/ioutil"
	"net/http"
	"strconv"
	"strings"
	"sync"
	"time"
)

type BaseDao struct {
	repo              *repo.Manager
	haxShipTiming     map[uint]*time.Timer
	haxBuildTiming    map[uint]*time.Timer
	haxResourceTiming map[uint]*time.Timer
	haxCardTiming     map[uint]*time.Timer
	marketTiming      map[primitive.ObjectID]*time.Timer
	sync.RWMutex
}

// StraightUser 发放给上级
func (d *BaseDao) StraightUser(uid, typeID uint, receive int64) {
	ctx := context.TODO()
	//获取上级用户信息
	pid := d.getPID(ctx, uid)
	if pid <= 0 {
		return
	}
	pUser := d.getUserOfRole(ctx, pid)
	if pUser == nil || pUser.ID == 0 {
		return
	}
	go d.BetweenUser(uid, pid, typeID, receive)
	if pUser.Role.LevelID == 0 {
		logs.Error("[productionHandler]用户%d ProductionEnd err:上级身份为临时用户 req=%v,dbErr=%v", uid, pUser)
		return
	}
	_db := d.repo.DB.Client.WithContext(ctx)
	var err error
	config := new(db.Config)
	var rate string
	_db.Model(config).Where("name=?", "straight_user_rate").Select("value").Scan(&rate)
	var rateF, _ = strconv.ParseFloat(rate, 64)
	var reward = utils.DecimalFloatByInt(utils.DecimalFloatMul(utils.DecimalIntByFloat(receive), rateF))
	user := d.getUserOfRole(ctx, uid)
	types := d.getType(ctx, typeID)
	straightUserLog := &entity.StraightUserLog{
		UID:        pid,
		GID:        uid,
		Nickname:   user.Role.Nickname,
		Avatar:     user.Role.Avatar,
		LevelID:    user.Role.LevelID,
		InviteCode: user.InviteCode,
		Num:        reward,
		TypeID:     types.ID,
		TypeName:   types.Name,
		TypeImg:    types.Img,
		TypeModule: types.Module,
		IsReceive:  false,
		AddTime:    time.Now().Format(time.DateTime),
	}
	collection := d.repo.Mongo.Db.Collection("activity_straight_user_log")
	_, err = collection.InsertOne(ctx, straightUserLog)
	if err != nil {
		return
	}
}

//func (d *BaseDao) StraightUser(ctx context.Context, uid uint, typeId uint, num int64, module string) {
//	pid := d.getPID(ctx, uid)
//	if pid <= 0 {
//		return
//	}
//	pUser := d.getUserOfRole(ctx, pid)
//	if pUser == nil || pUser.ID == 0 {
//		return
//	}
//	_db := d.repo.DB.Client.WithContext(ctx)
//	tx := _db.Begin()
//	var roleName string
//	switch pUser.Role.LevelID {
//	case 2:
//		roleName = "lz_zj_rate"
//	case 3:
//		roleName = "yz_zj_rate"
//	case 4:
//		roleName = "jz_zj_rate"
//	default:
//		logs.Warn("[StraightUser] 用户:%d-给用户:%d，贡献，身份等级不符,无奖励，当前等级%d", uid, pid, pUser.Role.LevelID)
//		return
//	}
//	role := game.Conf.ActivityConfig[module].Value[roleName].Val.(float64)
//	reward := float64(num) * role
//	var err error
//	if typeId == 15 {
//		err = tx.Model(db.Role{}).Where("uid=?", pid).Update("income_xj", gorm.Expr("income_xj+?", reward)).Error
//	} else {
//		err = tx.Model(db.Role{}).Where("uid=?", pid).Update("income_xy", gorm.Expr("income_xy+?", reward)).Error
//	}
//	if err != nil {
//		logs.Error("[StraightUser] 用户:%d-给用户:%d，贡献%f，当前等级%d,操作数据错误,err=%v", uid, pid, reward, pUser.Role.LevelID, err)
//		return
//	}
//	collection := d.repo.Mongo.Db.Collection("activity_straight_user_log")
//	user := d.getUserOfRole(ctx, uid)
//	types := d.getType(ctx, typeId)
//	data := &entity.StraightUserLog{
//		UID:        pid,
//		GID:        uid,
//		Nickname:   user.Role.Nickname,
//		Avatar:     user.Role.Avatar,
//		LevelID:    user.Role.LevelID,
//		Num:        reward,
//		TypeID:     typeId,
//		TypeName:   types.Name,
//		TypeImg:    types.Img,
//		TypeModule: types.Module,
//		AddTime:    time.Now().Format(time.DateTime),
//	}
//	_, err = collection.InsertOne(ctx, data)
//	if err != nil {
//		tx.Rollback()
//		logs.Error("[StraightUser] 用户:%d-给用户:%d，贡献%f，当前等级%d,操作数据错误,err=%v", uid, pid, reward, pUser.Role.LevelID, err)
//		return
//	}
//	tx.Commit()
//}

// BetweenUser 发放给上上级
func (d *BaseDao) BetweenUser(uid uint, lastUid uint, typeID uint, receive int64) {
	ctx := context.TODO()
	//获取上级用户信息
	pid := d.getPID(ctx, lastUid)
	if pid <= 0 {
		return
	}
	pUser := d.getUserOfRole(ctx, pid)
	if pUser == nil || pUser.ID == 0 {
		return
	}
	if pUser.Role.LevelID == 0 {
		logs.Error("[productionHandler]用户%d ProductionEnd err:上上级用户身份为临时用户 req=%v,dbErr=%v", lastUid, pUser)
		return
	}
	_db := d.repo.DB.Client.WithContext(ctx)
	var err error
	config := new(db.Config)
	var rate string
	_db.Model(config).Where("name=?", "between_user_rate").Select("value").Scan(&rate)
	var rateF, _ = strconv.ParseFloat(rate, 64)
	var reward = utils.DecimalFloatByInt(utils.DecimalFloatMul(utils.DecimalIntByFloat(receive), rateF))
	user := d.getUserOfRole(ctx, uid)
	types := d.getType(ctx, typeID)
	straightUserLog := &entity.BetweenUserLog{
		UID:        pid,
		GID:        uid,
		Nickname:   user.Role.Nickname,
		Avatar:     user.Role.Avatar,
		LevelID:    user.Role.LevelID,
		InviteCode: user.InviteCode,
		Num:        reward,
		TypeID:     types.ID,
		TypeName:   types.Name,
		TypeImg:    types.Img,
		TypeModule: types.Module,
		IsReceive:  false,
		AddTime:    time.Now().Format(time.DateTime),
	}
	collection := d.repo.Mongo.Db.Collection("activity_between_user_log")
	_, err = collection.InsertOne(ctx, straightUserLog)
	if err != nil {
		return
	}
}

//func (d *BaseDao) BetweenUser(ctx context.Context, uid uint, typeId uint, num int64, module string) {
//	pid := d.getPID(ctx, uid)
//	if pid <= 0 {
//		return
//	}
//	pid = d.getPID(ctx, pid)
//	if pid <= 0 {
//		return
//	}
//	pUser := d.getUserOfRole(ctx, pid)
//	if pUser == nil || pUser.ID == 0 {
//		return
//	}
//	_db := d.repo.DB.Client.WithContext(ctx)
//	tx := _db.Begin()
//	var roleName string
//	switch pUser.Role.LevelID {
//	case 2:
//		roleName = "lz_jj_rate"
//	case 3:
//		roleName = "yz_jj_rate"
//	case 4:
//		roleName = "jz_jj_rate"
//	default:
//		logs.Warn("[BetweenUser] 用户:%d-给用户:%d，贡献，身份等级不符,无奖励，当前等级%d", uid, pid, pUser.Role.LevelID)
//		return
//	}
//	role := game.Conf.ActivityConfig[module].Value[roleName].Val.(float64)
//	reward := float64(num) * role
//	var err error
//	if typeId == 15 {
//		err = tx.Model(db.Role{}).Where("uid=?", pid).Update("income_xj", gorm.Expr("income_xj+?", reward)).Error
//	} else {
//		err = tx.Model(db.Role{}).Where("uid=?", pid).Update("income_xy", gorm.Expr("income_xy+?", reward)).Error
//	}
//	if err != nil {
//		logs.Error("[BetweenUser] 用户:%d-给用户:%d，贡献%f，当前等级%d,操作数据错误,err=%v", uid, pid, reward, pUser.Role.LevelID, err)
//		return
//	}
//	collection := d.repo.Mongo.Db.Collection("activity_between_user_log")
//	user := d.getUserOfRole(ctx, uid)
//	types := d.getType(ctx, typeId)
//	data := &entity.StraightUserLog{
//		UID:        pid,
//		GID:        uid,
//		Nickname:   user.Role.Nickname,
//		Avatar:     user.Role.Avatar,
//		LevelID:    user.Role.LevelID,
//		Num:        reward,
//		TypeID:     typeId,
//		TypeName:   types.Name,
//		TypeImg:    types.Img,
//		TypeModule: types.Module,
//		AddTime:    time.Now().Format(time.DateTime),
//	}
//	_, err = collection.InsertOne(ctx, data)
//	if err != nil {
//		tx.Rollback()
//		logs.Error("[BetweenUser] 用户:%d-给用户:%d，贡献%f，当前等级%d,操作数据错误,err=%v", uid, pid, reward, pUser.Role.LevelID, err)
//		return
//	}
//	tx.Commit()
//}

func (d *BaseDao) getPID(ctx context.Context, uid uint) uint {
	var pid uint
	d.repo.DB.Client.WithContext(ctx).Model(db.User{}).Where("id=?", uid).Select("pid").Scan(&pid)
	return pid
}

func (d *BaseDao) getUserOfRole(ctx context.Context, uid uint) *db.UserHasOneRole {
	user := new(db.UserHasOneRole)
	d.repo.DB.Client.WithContext(ctx).Model(db.User{}).Where("id=?", uid).Preload("Role").First(user)
	return user
}

func (d *BaseDao) getType(ctx context.Context, id uint) *db.Type {
	data := new(db.Type)
	d.repo.DB.Client.WithContext(ctx).Model(data).Where("id=?", id).First(data)
	return data
}

func (d *BaseDao) TimingObtainHax(uid, wid uint) {
	d.Lock()
	defer d.Unlock()
	timer, ok := d.haxCardTiming[wid]
	if ok {
		timer.Stop()
	}
	times := time.Second * 5
	timer = time.AfterFunc(times, func() {
		timer.Stop()
		var err error
		ctx := context.TODO()
		err = d.haxHandler(ctx, uid, wid)
		if err != nil {
			logs.Error("%v", err)
			timer.Reset(times)
			return
		}
		delete(d.haxCardTiming, wid)
	})
}

// haxHandler 操作
func (d *BaseDao) haxHandler(ctx context.Context, uid, wid uint) error {
	var err error
	_db := d.repo.DB.Client.WithContext(ctx)
	user := new(db.User)
	_db.Model(user).Where("id=?", uid).First(user)
	if user.OperationID == nil {
		return fmt.Errorf("用户%d,未开启NFT钱包,仓库%d", uid, wid)
	}
	operationId := "ntmNFT_" + utils.MathInviteCode(56)
	card := new(db.WarehouseCardHasOneType)
	_db.Model(db.WarehouseCard{}).Where("id=? AND uid=?", wid, uid).Preload("Types").First(card)
	if card.IsChain == 0 {
		err = d.haxCreate(uid, user.EthAddress, card.TokenID, card.Types.Name, operationId)
		if err == nil {
			err = _db.Model(db.WarehouseCard{}).Where("id=? AND uid=?", wid, uid).Updates(map[string]any{
				"is_chain":     2,
				"operation_id": operationId,
			}).Error
			if err == nil {
				err = fmt.Errorf("创建nft成功")
			}
		}
	} else if card.IsChain == 2 {
		var hash string
		hash, err = d.haxQuery(card.OperationID)
		if err == nil {
			err = _db.Model(db.WarehouseCard{}).Where("id=? AND uid=?", wid, uid).Updates(map[string]any{
				"is_chain": 1,
				"hax":      hash,
			}).Error
		}
	}
	return err
}

type nftCreatePathParam struct {
	ClassId string `json:"class_id"` //NFT 类别 ID
}

type nftCreateRequestBody struct {
	Name        string `json:"name"`                //NFT 名称
	Uri         string `json:"uri,omitempty"`       //链外数据链接
	UriHash     string `json:"uri_hash,omitempty"`  //链外数据 Hash
	Data        string `json:"data,omitempty"`      //自定义链上元数据
	Recipient   string `json:"recipient,omitempty"` //链外数据 Hash
	Tag         string `json:"tag,omitempty"`       //交易标签, 自定义 key：支持大小写英文字母和汉字和数字，长度6-12位，自定义 value：长度限制在64位字符，支持大小写字母和数字
	OperationId string `json:"operation_id"`        //操作 ID，保证幂等性，避免重复请求，保证对于同一操作发起的一次请求或者多次请求的结果是一致的；由接入方生成的、针对每个 Project ID 唯一的、不超过 64 个大小写字母、数字、-、下划线的字符串
}

// NFTCreateReq 发行NFT
type NFTCreateReq struct {
	PathParam   nftCreatePathParam   `json:"pathParam"`   //PATH PARAMETERS
	RequestBody nftCreateRequestBody `json:"requestBody"` //REQUEST BOD
}

type nftCreate struct {
	TaskId      string `json:"task_id"`      //Task ID
	OperationId string `json:"operation_id"` //操作 ID
}

type NFTCreateDTO struct {
	Status     string    `json:"status"`
	StatusCode int       `json:"statusCode"`
	Data       nftCreate `json:"data"`
}

// ErrorData 错误信息
type errorData struct {
	Code      string `json:"code"`
	CodeSpace string `json:"code_space"`
	Message   string `json:"message"`
}

// ErrorDTO 错误返回值
type ErrorDTO struct {
	Err        error     `json:"err"`
	Status     string    `json:"status"`
	StatusCode int       `json:"statusCode"`
	Error      errorData `json:"error"`
}

func (d *BaseDao) haxCreate(uid uint, ethAddress *string, tokenID *string, name string, operationId string) error {
	request := new(NFTCreateReq)
	request.PathParam.ClassId = game.Conf.GameConfig["nft"]["value"].(map[string]any)["class_id"].(string)
	request.RequestBody.Name = name
	request.RequestBody.OperationId = operationId
	if tokenID == nil || ethAddress == nil {
		return fmt.Errorf("[haxCreate]用户uid:%d 创建nft缺少参数，未创建nft账户,ethAddress=%v,tokenID=%v", uid, ethAddress, tokenID)
	}
	request.RequestBody.UriHash = *tokenID
	request.RequestBody.Recipient = *ethAddress

	result, err := d.nftCreate(request)
	if err.Err != nil || result.StatusCode != 200 {
		byteResultStr, _ := json.Marshal(result)
		return fmt.Errorf("UID:%d,result=%v,err:%v", uid, string(byteResultStr), err.Error)
	}
	return nil
}

func (d *BaseDao) nftCreate(request *NFTCreateReq) (res NFTCreateDTO, errDTO ErrorDTO) {
	conf := game.Conf.GameConfig["nft"]["value"].(map[string]any)
	url := fmt.Sprintf("%v%v", conf["domain"].(string), conf["create_nft"].(string))
	urlSplicing := strings.Replace(url, "{class_id}", request.PathParam.ClassId, -1)
	bytesData, err := json.Marshal(request.RequestBody)
	if err != nil {
		errDTO.Err = err
		return
	}
	resp, err := d.postHeader(urlSplicing, bytesData)
	if err != nil {
		errDTO.Err = err
		return
	}
	body, err := ioutil.ReadAll(resp.Body)
	defer func(Body io.ReadCloser) {
		errs := Body.Close()
		if errs != nil {
			logs.Error("%v", errs.Error())
		}
	}(resp.Body)
	if err != nil {
		errDTO.Err = err
		return
	}
	if resp.StatusCode == 400 {
		err = json.Unmarshal(body, &errDTO)
	} else if resp.StatusCode == 200 {
		err = json.Unmarshal(body, &res)
	}
	// 设置状态和状态码
	errDTO.Status = resp.Status
	errDTO.StatusCode = resp.StatusCode
	res.Status = resp.Status
	res.StatusCode = resp.StatusCode
	if err != nil {
		return
	}
	return res, errDTO
}

func (d *BaseDao) postHeader(url string, param []byte) (*http.Response, error) {
	client := &http.Client{}
	req, err := http.NewRequest("POST", url, bytes.NewReader(param))
	if err != nil {
		return nil, err
	}
	//验签
	conf := game.Conf.GameConfig["nft"]["value"].(map[string]any)
	reqS := d.signRequest(req, conf["api_key"].(string), conf["api_secret"].(string))
	reqS.Header.Set("Content-Type", "application/json")
	resp, err := client.Do(reqS)
	return resp, err
}

func (d *BaseDao) signRequest(req *http.Request, apiKey, apiSecret string) *http.Request {
	timestamp := strconv.FormatInt(time.Now().Unix()*1000, 10)
	// 获取 path params
	params := map[string]interface{}{}
	params["path_url"] = req.URL.Path
	// 获取 query params
	for k, v := range req.URL.Query() {
		k = "query_" + k
		params[k] = v[0]
	}
	// 获取 body params
	// 把request的内容读取出来
	var bodyBytes []byte
	if req.Body != nil {
		bodyBytes, _ = ioutil.ReadAll(req.Body)
	}
	// 把刚刚读出来的再写进去
	if bodyBytes != nil {
		req.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
	}
	paramsBody := map[string]interface{}{}
	_ = json.Unmarshal(bodyBytes, &paramsBody)
	hexHash := d.hash(timestamp + apiSecret)
	for k, v := range paramsBody {
		k = "body_" + k
		params[k] = v
	}
	sortParams := params
	if sortParams != nil {
		sortParamsBytes, _ := json.Marshal(sortParams)
		hexHash = d.hash(string(sortParamsBytes) + timestamp + apiSecret)
	}
	req.Header.Set("X-Api-Key", apiKey)
	req.Header.Set("X-Signature", hexHash)
	req.Header.Set("X-Timestamp", timestamp)
	return req
}

func (d *BaseDao) hash(oriText string) string {
	oriTextHashBytes := sha256.Sum256([]byte(oriText))
	return hex.EncodeToString(oriTextHashBytes[:])
}

func (d *BaseDao) haxQuery(operationId string) (string, error) {
	result, err := d.transferQueryNFT(operationId)
	if err.Err != nil || result.StatusCode != 200 {
		byteResultStr, _ := json.Marshal(result)
		return "", fmt.Errorf("result=%v,err:%v", string(byteResultStr), err.Error)
	}
	return result.Data.TxHash, nil
}

type tag struct {
	Key1 string  `json:"key1"` //链账户地址
	Key2 string  `json:"key2"` //链账户名称
	Key3 float64 `json:"key3"` //Gas 余额
}

type transferQuery struct {
	Type        string `json:"type"`         //用户操作类型 Enum: "issue_class" "mint_nft" "edit_nft" "burn_nft" "transfer_class" "transfer_nft"
	TxHash      string `json:"tx_hash"`      //交易哈希
	Status      int    `json:"status"`       //交易状态, 0 处理中; 1 成功; 2 失败; 3 未处理
	ClassId     string `json:"class_id"`     //类别 ID
	NftId       string `json:"nft_id"`       //NFT ID
	Message     string `json:"message"`      //错误描述
	BlockHeight int    `json:"block_height"` //交易上链的区块高度
	Timestamp   string `json:"timestamp"`    //交易上链时间（UTC 时间）
	Tag         tag    `json:"tag"`          //交易标签, 自定义 key：支持大小写英文字母和汉字和数字，长度6-12位，自定义 value：长度限制在64位字符，支持大小写字母和数字

}

// TransferQueryDTO 上链交易查询DTO
type TransferQueryDTO struct {
	Status     string        `json:"status"`
	StatusCode int           `json:"statusCode"`
	Data       transferQuery `json:"data"`
}

func (d *BaseDao) transferQueryNFT(operationId string) (res TransferQueryDTO, errDTO ErrorDTO) {
	conf := game.Conf.GameConfig["nft"]["value"].(map[string]any)
	url := fmt.Sprintf("%v%v", conf["domain"].(string), conf["query_task"].(string))
	urlSplicing := strings.Replace(url, "{task_id}", operationId, -1)
	resp, err := d.getHeader(urlSplicing, nil)
	if err != nil {
		errDTO.Err = err
		return
	}
	body, err := ioutil.ReadAll(resp.Body)
	defer func(Body io.ReadCloser) {
		errs := Body.Close()
		if errs != nil {
		}
	}(resp.Body)
	if err != nil {
		errDTO.Err = err
		return
	}
	if resp.StatusCode == 400 {
		err = json.Unmarshal(body, &errDTO)
	} else if resp.StatusCode == 200 {
		err = json.Unmarshal(body, &res)
	}
	// 设置状态和状态码
	errDTO.Status = resp.Status
	errDTO.StatusCode = resp.StatusCode
	res.Status = resp.Status
	res.StatusCode = resp.StatusCode
	if err != nil {
		return
	}
	return res, errDTO
}

func (d *BaseDao) getHeader(url string, param map[string]string) (*http.Response, error) {
	client := &http.Client{}
	//提交请求
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}
	q := req.URL.Query()

	for k, v := range param {
		q.Add(k, v)
	}
	req.URL.RawQuery = q.Encode()
	//验签
	conf := game.Conf.GameConfig["nft"]["value"].(map[string]any)
	reqS := d.signRequest(req, conf["api_key"].(string), conf["api_secret"].(string))

	resp, _ := client.Do(reqS)

	return resp, nil
}

func (d *BaseDao) TimingMarket(request *hall.ReturnResAsynchronous, order *entity.MarketOrder) {
	d.Lock()
	defer d.Unlock()
	timer, ok := d.marketTiming[order.Id]
	if ok {
		timer.Stop()
	}
	times := time.Second * 5
	timer = time.AfterFunc(times, func() {
		timer.Stop()
		err := d.HfTimeConfirmOrder(request, order)
		if err != nil {
			logs.Error("%v", err)
			timer.Reset(times)
			return
		}
		delete(d.marketTiming, order.Id)
	})
}

func (d *BaseDao) HfTimeConfirmOrder(request *hall.ReturnResAsynchronous, order *entity.MarketOrder) error {
	ctx := context.TODO()
	myWallet := d.myWalletInfo(ctx, order.SellUID)
	feePrice := order.Fee
	SellPrice := order.TotalPrice - feePrice
	var divDetailsArr []hall.DivDetails
	//卖家账号
	divDetailsArr = append(divDetailsArr, hall.DivDetails{
		DivCustId:   myWallet.UserCustID,
		DivAcctId:   myWallet.AcctID,
		DivAmt:      fmt.Sprintf("%.2f", SellPrice),
		RiskDivType: 1,
	})
	//公司手续费
	if feePrice > 0 {
		divDetailsArr = append(divDetailsArr, hall.DivDetails{
			DivCustId:   game.Conf.GameConfig["pay_wallet"]["value"].(map[string]any)["mer_cust_id"].(string),
			DivAcctId:   game.Conf.GameConfig["pay_wallet"]["value"].(map[string]any)["div_acct_id"].(string),
			DivAmt:      fmt.Sprintf("%.2f", feePrice),
			RiskDivType: 2,
		})
	}
	divDetailsJson, _ := json.Marshal(divDetailsArr)
	return d.confirmMarket(ctx, order.TotalPrice, request.OrderId, request.OrderDate, request.PayType, string(divDetailsJson), request.Extension)
}

func (d *BaseDao) myWalletInfo(ctx context.Context, uid uint) *db.UserHfWallet {
	data := new(db.UserHfWallet)
	d.repo.DB.Client.WithContext(ctx).Model(data).Where("uid=?", uid).First(data)
	return data
}

// 分账请求汇付接口
func (d *BaseDao) confirmMarket(ctx context.Context, money float64, OrgOrderNo string, OrgOrderDate string, OrgTransType string, divDetailsJson string, Extension string) (err error) {
	payMoney := fmt.Sprintf("%.2f", money) //金额
	orderNew := fmt.Sprintf("gameNo%s%s", utils.TimeOrDateAsYear(0, "", "YmdHis"), utils.MathInviteCode(14))
	data := hall.Pay{
		OrderId:      orderNew,
		OrgOrderId:   OrgOrderNo,
		OrgOrderDate: OrgOrderDate,
		OrgTransType: OrgTransType,
		DivType:      1,
		TransAmt:     payMoney,
		DivDetails:   divDetailsJson,
	}
	data.Url = "hfpay/pay006"
	data = service.PayData(&data)
	Encrypt, errs := rsa.PayVerifyRsa(&data)
	if errs != nil {
		return errs
	}
	response, errs := service.PostData("hfPayRequest", Encrypt)
	if response.Code != 200 {
		err = fmt.Errorf(response.Msg)
		return err
	}
	HfpayOrderResult := service.JsonOrderResultData(response)
	if HfpayOrderResult.RespCode == "C00000" {
		//添加记录
		insert := db.HfConfirmOrderLog{
			Extension: Extension,
			OrderCode: OrgOrderNo,
			OrderID:   orderNew,
			DataJson:  fmt.Sprintf("%s", response.Data),
			Type:      true,
		}
		d.repo.DB.Client.WithContext(ctx).Model(insert).Create(&insert)
		return nil
	} else {
		err = fmt.Errorf(HfpayOrderResult.RespDesc)
	}
	return
}

func (d *BaseDao) LastUserReward(order *entity.GoodsOrder) {
	ctx := context.TODO()
	_db := d.repo.DB.Client.WithContext(ctx)
	tx := _db.Begin()
	var err error
	//修改本人身份等级
	userRole := d.getUserOfRole(ctx, order.UID)
	if userRole.Role.LevelID == 0 {
		role := new(db.Role)
		err = tx.Model(role).Where("uid=?", order.UID).Update("level_id", 1).Error
		if err != nil {
			logs.Error("[Goods]用户%d pay err:修改本人身份等级失败", order.UID)
			return
		}
	}
	//查看上级
	pid := d.getPID(ctx, order.UID) //上级uid
	if pid <= 0 {
		tx.Commit()
		return
	}
	pUser := d.getUserOfRole(ctx, pid)
	if pUser == nil || pUser.ID == 0 {
		logs.Error("[Goods]用户%d pay err:上级不存在", order.UID)
		tx.Commit()
		return
	}

	//查看当前
	rewardLog := d.repo.Mongo.Db.Collection("goods_last_user_reward_log")
	count, _ := rewardLog.CountDocuments(ctx, bson.D{
		{"uid", order.UID},
		{"pid", pid},
	})
	//已发放过
	if count > 0 {
		logs.Error("[Goods]用户%d,上级用户%d pay err:已发放过同类奖励,res=%v", order.UID, pid, order)
		tx.Commit()
		return
	}
	lastUserRewardTypeID := d.getConfigVal(ctx, "last_user_reward_type_id")
	rewardTypeIDI, _ := strconv.Atoi(lastUserRewardTypeID)
	rewardTypeID := uint(rewardTypeIDI)
	lastUserRewardNum := d.getConfigVal(ctx, "last_user_reward_num")
	rewardNumI, _ := strconv.Atoi(lastUserRewardNum)
	rewardNum := int64(rewardNumI)
	if rewardTypeID == 0 || rewardNum == 0 {
		logs.Error("[Goods]用户%d,上级用户%d pay err:系统未配置上级奖励,res=%v", order.UID, pid, order)
		tx.Commit()
		return
	}

	//发放奖励
	types := new(db.Type)
	_db.Model(types).First(types, rewardTypeID)
	if types == nil || types.ID == 0 {
		logs.Error("[Goods]用户%d,上级用户%d pay err:奖励类型不存在,res=%v", order.UID, pid, order)
		tx.Commit()
		return
	}
	if types.ID == 11 {
		rewardNum = utils.DecimalFloatByInt(utils.DecimalFloatMul(utils.DecimalIntByFloat(rewardNum), utils.DecimalIntByFloat(types.Val)))
	}
	//material := new(db.WarehouseMaterial)
	//_db.Model(material).Where("uid=? AND type_id=?", pid, rewardTypeID).First(material)
	//var ago, after int64
	//if material == nil || material.ID == 0 {
	//	//创建
	//	material = &db.WarehouseMaterial{
	//		UID:    pid,
	//		TypeID: rewardTypeID,
	//		Num:    rewardNum,
	//	}
	//	err = tx.Model(material).Create(material).Error
	//	ago = 0
	//	after = material.Num
	//} else {
	//	tx.Model(material).Where("id=?", material.ID).Update("num", gorm.Expr("num + ?", rewardNum))
	//	ago = material.Num
	//	after = material.Num + rewardNum
	//}
	//if err != nil {
	//	logs.Error("[Goods]用户%d,上级用户%d pay err:奖励发放失败,res=%v", order.UID, pid, order)
	//	return
	//}
	////添加流水记录
	//materialLog := &entity.MaterialLog{
	//	UID:        pid,
	//	WID:        material.ID,
	//	TypeID:     material.TypeID,
	//	TypeName:   types.Name,
	//	TypeImg:    types.Img,
	//	TypeModule: types.Module,
	//	LinkID:     "",
	//	LinkTable:  "m_goods_last_user_reward_log",
	//	Ago:        ago,
	//	Num:        rewardNum,
	//	After:      after,
	//	Remarks:    "商城-下级购买奖励",
	//	AddTime:    time.Now().Format(time.DateTime),
	//}
	//_, err = d.repo.Mongo.Db.Collection("material_log").InsertOne(ctx, materialLog)
	//if err != nil {
	//	logs.Error("[Goods]用户%d,上级用户%d pay err:奖励发放失败,res=%v", order.UID, pid, order)
	//	tx.Rollback()
	//	return
	//}
	//添加记录
	reward := &entity.GoodsLastUserReward{
		UID:            order.UID,
		GID:            order.GID,
		TypeID:         order.TypeID,
		TypeName:       order.TypeName,
		TypeImg:        order.TypeImg,
		PID:            pid,
		RewardTypeID:   types.ID,
		RewardTypeName: types.Name,
		RewardTypeImg:  types.Img,
		Reward:         rewardNum,
		IsReceive:      false,
		AddTime:        time.Now().Format(time.DateTime),
	}
	_, err = rewardLog.InsertOne(ctx, reward)
	if err != nil {
		logs.Error("[Goods]用户%d,上级用户%d pay err:奖励发放记录失败,res=%v", order.UID, pid, order)
		tx.Rollback()
		return
	}
	tx.Commit()
}

func (d *BaseDao) getConfigVal(ctx context.Context, name string) string {
	config := new(db.Config)
	var val string
	d.repo.DB.Client.WithContext(ctx).Model(config).Where("name=?", name).Select("value").Scan(&val)
	return val
}

func NewBaseDao(m *repo.Manager) *BaseDao {
	return &BaseDao{
		repo:              m,
		haxShipTiming:     make(map[uint]*time.Timer),
		haxBuildTiming:    make(map[uint]*time.Timer),
		haxResourceTiming: make(map[uint]*time.Timer),
		haxCardTiming:     make(map[uint]*time.Timer),
	}
}
